﻿using System;
using System.Text;
using La.Code.SocketUtil;


namespace LiAnProxy
{
    /// <summary>
    /// Socket代理
    /// </summary>
    public class ProxySocket
    {
        /// <summary>
        /// 异常日志 委托
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="content"></param>
        /// <param Name="ex"></param>
        public delegate void ErrorLogEventHandler(IDataTransmit sender, string content, Exception ex);
        /// <summary>
        /// 错误日志 事件
        /// </summary>
        public event ErrorLogEventHandler WriteErrorLogEvent;
        /// <summary>
        /// 
        /// </summary>
        public TcpService Server;
        /// <summary>
        /// 代理对象
        /// </summary>
        public ProxyModel SocketModel { get; set; }

        public ProxySocket(ProxyModel socketModel)
            : this(socketModel, 1000)
        {
        }
        public ProxySocket(ProxyModel socketModel, int proxyMax)
        {
            socketModel.ProxyType = ProxyType.Socket;
            socketModel.ProxyMax = proxyMax;
            //在指定端口上建立监听线程
            Server = new TcpService(socketModel.ProxyPort, socketModel.ProxyMax, socketModel.ProxyIp);
            Server.Connected += server_Connected;
            Server.DisConnect += server_DisConnect;
            //启动服务
            Server.Start();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="proxyName">代理名字</param>
        /// <param name="proxyPort">代理端口</param>
        /// <param name="targetIp">目标地址</param>
        /// <param name="targetPort">目标端口</param> 
        public ProxySocket(string proxyName, int proxyPort, string targetIp, int targetPort)
            : this(proxyName, "0.0.0.0", proxyPort, targetIp, targetPort)
        {

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="proxyName"></param>
        /// <param name="proxyIp">代理地址</param> 
        /// <param name="proxyPort">代理端口</param>
        /// <param name="targetIp">目标地址</param>
        /// <param name="targetPort">目标端口</param> 
        public ProxySocket(string proxyName, string proxyIp, int proxyPort, string targetIp, int targetPort)
            : this(proxyName, proxyIp, 1000, proxyPort, targetIp, targetPort, 60)
        {

        }

        /// <summary>
        /// 
        /// </summary> 
        /// <param name="proxyMax">代理服务的最大数量</param>
        /// <param name="proxyName"></param>
        /// <param name="proxyPort">代理端口</param>
        /// <param name="targetIp">目标地址</param>
        /// <param name="targetPort">目标端口</param>
        /// <param name="targetTimeOut">超时时间</param>
        public ProxySocket(string proxyName, int proxyPort, int proxyMax, string targetIp, int targetPort, int targetTimeOut)
            : this(proxyName, "0.0.0.0", proxyMax, proxyPort, targetIp, targetPort, targetTimeOut)
        {
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="proxyName"></param>
        /// <param name="proxyIp">代理地址</param>
        /// <param name="proxyMax">代理服务的最大数量</param>
        /// <param name="proxyPort">代理端口</param>
        /// <param name="targetIp">目标地址</param>
        /// <param name="targetPort">目标端口</param>
        /// <param name="targetTimeOut">超时时间</param>
        public ProxySocket(string proxyName, string proxyIp, int proxyMax, int proxyPort, string targetIp, int targetPort, int targetTimeOut)
        {
            try
            {
                SocketModel = new ProxyModel
                {
                    ProxyName = proxyName,
                    ProxyType = ProxyType.Socket,
                    TargetIp = targetIp,
                    TargetPort = targetPort,
                    TargetTimeOut = targetTimeOut,
                    ProxyIp = proxyIp,
                    ProxyPort = proxyPort,
                    ProxyMax = proxyMax
                };
                //在指定端口上建立监听线程
                Server = new TcpService(SocketModel.ProxyPort, SocketModel.ProxyMax, SocketModel.ProxyIp);
                Server.Connected += server_Connected;
                Server.DisConnect += server_DisConnect;


            }
            catch (Exception ex)
            {
                WriteErrorLogEvent(null, "连接处理", ex);
            }
        }

        public void Start()
        {
            //启动服务
            Server.Start();
        }

        public void Stop()
        {
            Server.Stop();
        }

        /// <summary>
        /// 连接处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void server_Connected(IDataTransmit sender, NetEventArgs e)
        {
            try
            {
                //接受委托
                sender.ReceiveData += sender_ReceiveData;
                //接收数据
                sender.Start();
            }
            catch (Exception ex)
            {
                WriteErrorLogEvent(sender, "连接处理", ex);
            }
        }
        /// <summary>
        /// 接受处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void sender_ReceiveData(IDataTransmit sender, NetEventArgs e)
        {
            try
            {
                Encoding encoding = Encoding.GetEncoding("utf-8");
                //接受请求数据
                byte[] data = (byte[])e.EventArg;
                Write("接收：" + encoding.GetString(data, 0, data.Length));
                //向目标地址请求数据
                TcpClient client = new TcpClient(SocketModel.TargetIp, SocketModel.TargetPort, SocketModel.TargetTimeOut, false);
                byte[] resurlt = client.SendAndReceive(data);
                if (resurlt != null)
                {
                    Write("返回：" + encoding.GetString(resurlt, 0, resurlt.Length));
                    //返回结果
                    sender.Send(resurlt);

                }
                else
                {
                    sender.Send("");
                    sender.TcpSocket.Close();

                }

            }
            catch (Exception ex)
            {
                WriteErrorLogEvent(sender, "接受处理", ex);
            }
        }


        /// <summary>
        /// 断开连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void server_DisConnect(IDataTransmit sender, NetEventArgs e)
        {
            try
            {
                //string tempKey = "";


            }
            catch (Exception ex)
            {
                WriteErrorLogEvent(sender, "断开连接", ex);
            }
        }
        void Write(string mes)
        {
            if (ShowMesEvent != null)
                ShowMesEvent(mes, 1);
            //var log = LogFactory.GetLogger(GetType());
            //log.Info(mes);
        }
        /// <summary>
        /// 消息时间
        /// </summary>
        public event ShowMesHandle ShowMesEvent;

    }
}
